package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author friday
 * @since 2023-11-09
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    private final IInteractionReplyService replyService;
    private final InteractionReplyMapper replyMapper;
    private final UserClient userClient;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;
    /**
     * 保存提问
     * @param questionDTO
     */
    @Override
    public void saveQuestion(QuestionFormDTO questionDTO) {
        //1.获取当前登录用户Id
        Long userId = UserContext.getUser();
        //2.dto转po
        InteractionQuestion question = BeanUtils.copyBean(questionDTO, InteractionQuestion.class);
        question.setUserId(userId);
        //3.保存
        this.save(question);
    }

    /**
     * 更新提问
     * @param id
     * @param questionDTO
     */
    @Override
    public void updateQuestion(Long id, QuestionFormDTO questionDTO) {
        //1.校验
        if (StringUtils.isBlank(questionDTO.getTitle()) ||
                StringUtils.isBlank(questionDTO.getDescription()) ||
                questionDTO.getAnonymity() == null){
            throw new BadRequestException("非法参数");
        }
        //校验Id
        InteractionQuestion question = this.getById(id);
        if (question == null){
            throw new BadRequestException("提问不存在");
        }

        //修改只能修改自己的提问
        if (!question.getUserId().equals(UserContext.getUser())){
            throw new BadRequestException("不能修改别人的提问");
        }

        //2.dto转po
        question.setTitle(questionDTO.getTitle());
        question.setDescription(questionDTO.getDescription());
        question.setAnonymity(questionDTO.getAnonymity());

        //3.更新
        this.updateById(question);
    }

    //分页查询互动问题
    @Override
    public PageDTO<QuestionVO> queryQuestionPage(QuestionPageQuery query) {
//        //1.校验 参数courseId
//        if (query.getCourseId() == null) {
//            throw new BadRequestException("课程为空！");
//        }
        // 1.参数校验，课程id和小节id不能都为空
        Long courseId = query.getCourseId();  //前端没有传courseId，课程id
        Long sectionId = query.getSectionId();
        if (courseId == null && sectionId == null) {
            throw new BadRequestException("课程id和小节id不能都为空");
        }
        //2.获取登录用户Id
        Long userId = UserContext.getUser();
        //3.分页查询互动问题interaction_question 条件：courseId onlyMine为true才会有userId 小节不为空 hidden为false 分页查询 按提问时间降序
        Page<InteractionQuestion> page = this.lambdaQuery()
                .select(InteractionQuestion.class, tableFieldInfo -> !tableFieldInfo.getProperty().equals("description")) //指定不查询的字段
                .eq(InteractionQuestion::getCourseId, query.getCourseId())
                .eq(query.getOnlyMine(), InteractionQuestion::getUserId, userId)
                .eq(query.getSectionId() != null, InteractionQuestion::getSectionId, query.getSectionId())
                .eq(InteractionQuestion::getHidden, false)
                .page(query.toMpPage("create_time", false));

        List<InteractionQuestion> records = page.getRecords();
        if (CollUtils.isEmpty(records)){
            return PageDTO.empty(page);
        }
        //3.1 过滤出最新回答的id
        Set<Long> latestAnswerIds = new HashSet<>();
        Set<Long> userIds = new HashSet<>();  //互动问题的用户的Ids集合
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()){   //匿名提问，不显示用户名和头像
                userIds.add(record.getUserId());
            }

            if (record.getLatestAnswerId()!= null){
                latestAnswerIds.add(record.getLatestAnswerId());
            }
        }
        /*Set<Long> latestAnswerIds = records.stream()
                .filter(c -> c.getLatestAnswerId() != null)
                .map(InteractionQuestion::getLatestAnswerId)
                .collect(Collectors.toSet());*/

        //4.根据最新回答interaction_reply  Id，批量查询回答信息
        Map<Long, InteractionReply> replyMap = new HashMap<>();
        if (CollUtils.isNotEmpty(latestAnswerIds)){  //集合可能为空，所以要判断
            //List<InteractionReply> replyList = replyService.listByIds(latestAnswerIds);
            List<InteractionReply> replyList = replyService.list(Wrappers.<InteractionReply>lambdaQuery()
                    .in(InteractionReply::getId, latestAnswerIds)
                    .eq(InteractionReply::getHidden, false));

            for (InteractionReply reply : replyList) {
                if (!reply.getAnonymity()){
                    userIds.add(reply.getUserId());  //将最新回答者id存入userIds
                }
                replyMap.put(reply.getId(), reply);
            }

            //将 replyList 转为 map<Long(id) ,InteractionReply>
            //replyMap = replyList.stream().collect(Collectors.toMap(InteractionReply::getId, v -> v));
        }

        //5.远程调用用户服务，获取用户信息 批量
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userDTOMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, v -> v));

        //6封装vo返回
        List<QuestionVO> voList = new ArrayList<>();
        for (InteractionQuestion record : records) {
            QuestionVO vo = BeanUtils.copyBean(record, QuestionVO.class);
            if (!vo.getAnonymity()){
                UserDTO userDTO = userDTOMap.get(vo.getUserId());
                if (userDTO!= null){
                    vo.setUserName(userDTO.getName());
                    vo.setUserIcon(userDTO.getIcon());
                }
            }
            InteractionReply reply = replyMap.get(record.getLatestAnswerId());
            if (reply!= null){
                if (!record.getAnonymity()){  //最新回答如果是非匿名，才设置最新回答者
                    UserDTO userDTO = userDTOMap.get(reply.getUserId());
                    if (userDTO != null){
                        vo.setLatestReplyUser(userDTO.getName()); //最新回答者
                    }
                }
                vo.setLatestReplyContent(reply.getContent()); //最新回答内容
            }
            voList.add(vo);
        }
        return PageDTO.of(page, voList);
    }

    /**
     * 根据id查询问题详情
     * @param id
     * @return
     */
    @Override
    public QuestionVO queryQuestionById(Long id) {
        //1.校验
        if (id == null){
            throw new BadRequestException("id为空");
        }
        //2.查询互动问题表，按主键返回
        InteractionQuestion question = this.getById(id);
        if (question == null){
            throw new BadRequestException("问题不存在");
        }
        //3.如果该问题=管理员设置了隐藏，返回空
        if (question.getAnonymity()){
            return null;
        }
        //4.封装vo返回
        QuestionVO questionVO = BeanUtils.copyBean(question, QuestionVO.class);
        //5.如果用户是匿名提问，不用查询提问者的名称和头像
        if (!question.getAnonymity()){
            //6.远程调用用户服务，获取用户信息
            UserDTO userDTO = userClient.queryUserById(question.getUserId());
            if (userDTO!= null){
                questionVO.setUserName(userDTO.getName());
                questionVO.setUserIcon(userDTO.getIcon());
            }
        }

        return questionVO;
    }

    //分页查询管理端互动问题
    @Override
    public PageDTO<QuestionAdminVO> queryQuestionPageAdmin(QuestionAdminPageQuery query) {
        //0.如果用户传了课程的名称参数，则从es中获取该名称对应的课程Id
        List<Long> cids = null;
        if (StringUtils.isNotBlank(query.getCourseName())){
            cids = searchClient.queryCoursesIdByName(query.getCourseName());//通过feign远程调用搜索服务，从es中搜索该关键字对应的课程id
            if (CollUtils.isEmpty(cids)){
                return PageDTO.empty(0L,0L);
            }
        }

        //1.查询互动问题表  前端传条件了就添加   分页 排序按时间排序
        Page<InteractionQuestion> page = this.lambdaQuery()
                .in(CollUtils.isNotEmpty(cids),InteractionQuestion::getCourseId, cids)
                .eq(query.getStatus() != null, InteractionQuestion::getStatus, query.getStatus())
                .between(query.getBeginTime() != null && query.getEndTime() != null,
                        InteractionQuestion::getCreateTime, query.getBeginTime(), query.getEndTime())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = page.getRecords();
        if (CollUtils.isEmpty(records)){
            return PageDTO.empty(0L,0L);
        }

        Set<Long> userIds = new HashSet<>();  //提问者id
        Set<Long> courseIds = new HashSet<>();  //课程id
        Set<Long> chapterAndSectionIds = new HashSet<>(); //章id和节id
        for (InteractionQuestion record : records) {
            userIds.add(record.getUserId());
            courseIds.add(record.getCourseId());
            chapterAndSectionIds.add(record.getChapterId()); //章id
            chapterAndSectionIds.add(record.getSectionId()); //章节id
        }

        //2.远程调用用户服务，获取用户信息
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        if (CollUtils.isEmpty(userDTOS)){
            throw new BizIllegalException("用户不存在！");
        }
        Map<Long, UserDTO> userDTOMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, v -> v));

        //3.远程调用用户服务，获取课程信息
        List<CourseSimpleInfoDTO> cinfos = courseClient.getSimpleInfoList(courseIds);
        if (CollUtils.isEmpty(cinfos)){
            throw new BizIllegalException("课程不存在！");
        }
        Map<Long, CourseSimpleInfoDTO> cinfoMap = cinfos.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, v -> v));

        //4.远程调用用户服务，获取章节信息
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(chapterAndSectionIds);
        if (CollUtils.isEmpty(cataSimpleInfoDTOS)){
            throw new BizIllegalException("章节信息不存在！");
        }
        Map<Long, String> cataIndoDTO = cataSimpleInfoDTOS.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, v -> v.getName()));

        //6.封装vo返回
        List<QuestionAdminVO> voList = new ArrayList<>();
        for (InteractionQuestion record : records) {
            QuestionAdminVO adminVO = BeanUtils.copyBean(record, QuestionAdminVO.class);
            UserDTO userDTO = userDTOMap.get(record.getId());
            if (userDTO!= null){
                adminVO.setUserName(userDTO.getName());
            }
            CourseSimpleInfoDTO cinfoDTO = cinfoMap.get(record.getCourseId());
            if (cinfoDTO!= null){
                adminVO.setCourseName(cinfoDTO.getName());
                //5.获取分类信息
                List<Long> categoryIds = cinfoDTO.getCategoryIds(); //一二三级分类id
                String categoryNames = categoryCache.getCategoryNames(categoryIds); //一二三级分类名称
                adminVO.setCategoryName(categoryNames); //三级分类名称，拼接宁段
            }

            adminVO.setChapterName(cataIndoDTO.get(record.getChapterId()));//章名称
            adminVO.setSectionName(cataIndoDTO.get(record.getSectionId()));//节名称

            voList.add(adminVO);
        }
        return PageDTO.of(page,voList);
    }

    //根据id删除当前用户问题
    @Override
    @Transactional
    public void deleteById(Long id) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.查询当前问题
        InteractionQuestion q = getById(id);
        if (q == null) {
            return;
        }
        // 3.判断是否是当前用户的问题
        if (!q.getUserId().equals(userId)) {
            // 不是，抛出异常
            throw new BadRequestException("无权删除他人的问题");
        }
        // 4.删除问题
        removeById(id);
        // 5.删除答案
        replyMapper.delete(
                new QueryWrapper<InteractionReply>().lambda().eq(InteractionReply::getQuestionId, id)
        );
    }

    //管理端隐藏或显示问题
    @Override
    public void hiddenQuestion(Long id, Boolean hidden) {
        // 1.更新问题
        InteractionQuestion question = new InteractionQuestion();
        question.setId(id);
        question.setHidden(hidden);
        updateById(question);
    }

    //管理端根据id查询问题详情
    @Override
    public QuestionAdminVO queryQuestionByIdAdmin(Long id) {
        // 1.根据id查询问题
        InteractionQuestion question = getById(id);
        if (question == null) {
            return null;
        }
        // 2.转PO为VO
        QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
        // 3.查询提问者信息
        UserDTO user = userClient.queryUserById(question.getUserId());
        if (user != null) {
            vo.setUserName(user.getName());
            vo.setUserIcon(user.getIcon());
        }
        // 4.查询课程信息
        CourseFullInfoDTO cInfo = courseClient.getCourseInfoById(
                question.getCourseId(), false, true);
        if (cInfo != null) {
            // 4.1.课程名称信息
            vo.setCourseName(cInfo.getName());
            // 4.2.分类信息
            vo.setCategoryName(categoryCache.getCategoryNames(cInfo.getCategoryIds()));
            // 4.3.教师信息
            List<Long> teacherIds = cInfo.getTeacherIds();
            List<UserDTO> teachers = userClient.queryUserByIds(teacherIds);
            if(CollUtils.isNotEmpty(teachers)) {
                vo.setTeacherName(teachers.stream()
                        .map(UserDTO::getName).collect(Collectors.joining("/")));
            }
        }
        // 5.查询章节信息
        List<CataSimpleInfoDTO> catas = catalogueClient.batchQueryCatalogue(
                List.of(question.getChapterId(), question.getSectionId()));
        Map<Long, String> cataMap = new HashMap<>(catas.size());
        if (CollUtils.isNotEmpty(catas)) {
            cataMap = catas.stream()
                    .collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        vo.setChapterName(cataMap.getOrDefault(question.getChapterId(), ""));
        vo.setSectionName(cataMap.getOrDefault(question.getSectionId(), ""));
        // 6.封装VO
        return vo;
    }
}
